/* 
 * File:   main.cpp
 * Author: max
 *
 * Created on October 19, 2012, 9:29 PM
 */

#include <cstdlib>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include "Cliente.h"
#include "Posicion.h"

using namespace std;
using namespace TP::Comunicacion;

#define SUCCESS_EXIT 0
#define CONNECTION_FAILED 1
#define INVALID_SERVICE_REFERENCE 2
#define INVALID_ARGS 3

void parsearComando (vector<string>& comando, const string& pDescriptor);

int main(int argc, char** argv) {
    
    int val = SUCCESS_EXIT;
    
    try
    {
        // Verifico la cantidad de parametros de la aplicacion.
        if (argc != 3)
            throw INVALID_ARGS;

        // Interpreto la referencia al servicio de los parametros.
        string item = "";
        vector<string> comando;
        std::stringstream ss (argv[1]);

        while (std::getline(ss, item, ':' ))
            comando.push_back(item);

        if (comando.size() != 2)
            throw INVALID_SERVICE_REFERENCE;
        
        // Defino el jugador.
        Jugador* jugador = new Jugador (argv[2]);
        
        Cliente cliente (jugador, comando[0], comando[1], cout);
        cliente.Iniciar();

        try
        {
            while (std::getline(std::cin, item, '\n'))
            {
                vector<string> comando;
                parsearComando (comando, item);
                
                if (comando[0] == "S" ||comando[0]  == "s")
                    break;
                
                else if (comando[0] == "P" || comando[0] == "p")
                {
                    Partida* partida = cliente.getPartida();
                    
                    if (partida)
                        cout << partida->aXML() << endl;
                    else
                        cout << "El jugador " << jugador->getNombre() << "no se encuentra jugando partida alguna." << endl;
                }

                else if (comando[0] == "EX" || comando[0] == "ex")
                {
                    cliente.abandonarPartida();
                }
                
                else if (comando[0] == "UP" || comando[0] == "up")
                {
                    if (comando.size() != 2)
                        cout << "Formato de comnado incorecto." << endl;
                    else
                        cliente.unirAPartida(comando[1]);
                }

                else if (comando[0] == "P1000" || comando[0] == "p1000")
                {
                    int cont = 1000;
                    while (cont > 0)
                    {
                        Partida* partida = cliente.getPartida();

                        if (partida)
                            cout << partida->aXML() << endl;
                        else
                            cout << "El jugador " << jugador->getNombre() << "no se encuentra jugando partida alguna." << endl;
                        cont--;
                    }
                }
                
                else if (comando[0] == "A" || comando[0] == "a")
                {
                    if (comando.size() != 3)
                        cout << "Formato de comando invalido." << endl;
                    else
                    {
                        int x = 0, y = 0;
                        
                        
                        std::stringstream strstream;
                        strstream << comando [1];
                        strstream >> x;

                        std::stringstream strstreamY;
                        strstreamY << comando [2];
                        strstreamY >> y;

                        cout << "X:" << x << "; Y:" << y << endl;
                        
                        cliente.atacar (new Posicion (x,y));
                    }
                }

                else if (comando[0] == "A1000" || comando[0] == "a1000")
                {
                    if (comando.size() != 3)
                        cout << "Formato de comando invalido." << endl;
                    else
                    {
                        int count = 1000;
                        while (count > 0)
                        {
                            int x = 0, y = 0;


                            std::stringstream strstream;
                            strstream << comando [1];
                            strstream >> x;

                            std::stringstream strstreamY;
                            strstreamY << comando [2];
                            strstreamY >> y;

                            cout << "X:" << x << "; Y:" << y << endl;

                            cliente.atacar (new Posicion (x,y));

                            count--;
                        }
                    }
                }
                else if (comando[0] == "LM" || comando[0] == "lm") {
                    vector<string> vec = cliente.listarMundos();
                    if (vec.size() != 0)
                    {
                        for(vector<string>::iterator it = vec.begin(); it != vec.end(); ++it)
                            cout << (*it) << endl;
                    }
                    else
                        cout << "No hay mundos definidos." << endl;
                }

                else if (comando[0] == "LN" || comando[0] == "ln") {
                    
                    if (comando.size() == 2)
                    {
                        vector<string> vec = cliente.listarNiveles(comando [1]);

                        if (vec.size() != 0)
                        {
                            for(vector<string>::iterator it = vec.begin(); it != vec.end(); ++it)
                                cout << (*it) << endl;
                        }
                        else
                            cout << endl << "No existen niveles asociados al mundo " << comando[1] << endl;
                    }
                    else
                        cout << endl << "Comando incorrecto.  Pruebe ln <nombre_mundo>." << endl;
                }
                
                else if (comando[0] == "LP" || comando[0] == "lp") {
                    vector<string> vec = cliente.listarPartidas();
                    if (vec.size() != 0)
                    {
                        for(vector<string>::iterator it = vec.begin(); it != vec.end(); ++it)
                            cout << (*it) << endl;
                    }
                    else
                        cout << "No existen partidas corriendo en el servidor." << endl;
                }
                
                else if (comando[0] == "CP" || comando[0] == "cp")
                {
                    if (comando.size() == 4)
                    {
                        std::stringstream strstream (comando[2]);
                        unsigned int idNivel = -1;
                        strstream >> idNivel;

                        Partida* partida = cliente.crearPartida(comando[1], idNivel, comando[3]);
                        if (partida)
                            cout << endl << partida->aXML() << endl;
                    }
                    else
                        cout << "Parametros insuficientes para crear la partida de juego." << endl;
                }
                else
                    cout << "Comando invalido..." << endl;
            }
        }
        catch (Excepcion& pEx)
        {
            cout << pEx.what() << endl;
        }
        cliente.Finalizar();
    }
    catch (Excepcion& pEx)
    {
        cout << pEx.what() << endl;
        val = CONNECTION_FAILED;
    }
    catch (int pEx)
    {
        val = pEx;
    }

    return val;
}

void parsearComando (vector<string>& comando, const string& pDescriptor){
    
    std::stringstream stream (pDescriptor);
    string item = "";
    
    while (std::getline (stream, item, ' '))
        if (item.length() > 0)
            comando.push_back(item);
}